package com.nulldev.util.web.nTubeExtensions.services.SoundCloud;

import java.util.List;

import com.nulldev.util.JVM.JVM;
import com.nulldev.util.VariableAPI.ArrayUtils;
import com.nulldev.util.VariableAPI.ArrayUtils.StringArrayUtils;
import com.nulldev.util.VariableAPI.StringsUtil;
import com.nulldev.util.languages.json.uniapi.UniJsonIterableValue;
import com.nulldev.util.languages.json.uniapi.UniJsonValue;
import com.nulldev.util.logging.Logger;
import com.nulldev.util.logging.LoggerFactory;
import com.nulldev.util.web.HttpClient.HttpClient;
import com.nulldev.util.web.flexibleKit.jfvParse.Document;
import com.nulldev.util.web.flexibleKit.jfvParse.Element;
import com.nulldev.util.web.flexibleKit.jfvParse.JFiveParse;

public class SoundcloudExtractor {
	/*
	 * CLIENT_ID required sourced from
	 * 
	 * Stream JSON URL: [url]?client_id=<client_id>
	 */
	private static final Logger log = LoggerFactory.getLoggerD(true);

	public static UniJsonValue getTracks(final String clientID, final String trackID) {
		try {
			final String URL = "https://api.soundcloud.com/i1/tracks/" + trackID + "/streams?client_id=" + clientID;
			return UniJsonValue.parse(HttpClient.getString().url(URL).create().dataThenClose());
		} catch (Exception e) {
			final UniJsonValue out = UniJsonValue.object();
			out.add("error", "Invalid client ID!");
			return out;
		}
	}

	private static final String[] ACCEPTED_IDs = new String[]
		{ "https://a-v2.sndcdn.com/assets/49-3d38e092-3.js" };

	public static String getAPIKey(final String songURL) throws Exception {
		if (!songURL.contains("soundcloud.com/")) {
			return null;
		}
		final String data0 = HttpClient.getString().url(songURL).create().dataThenClose();
		final Document doc0 = JFiveParse.parse(data0);
		String clientIDURL = null;
		final List<Element> es = doc0.getElementsByTagName("script");
		log.debug("[getAPIKey] script elements: " + es.size());
		for (int i = 0; i < es.size(); i++) {
			final Element e = es.get(i);
			final boolean isSecondToLast = i == (es.size() - 2);
			final String src = e.getAttribute("src");
			if (src == null)
				continue;
			if (src.length() == 0) {
				continue;
			}
			if (src != null && (src.startsWith("https://a-v2.sndcdn.com/assets/app-") || StringArrayUtils.containsString(ACCEPTED_IDs, src))
					|| (isSecondToLast)) {
				clientIDURL = src;
				break;
			}
		}
		if (clientIDURL == null) {
			if (!es.isEmpty()) {
				final String data = HttpClient.getString().url(es.get(es.size() - 2).getAttribute("src")).create().dataThenClose();
				final String clientID = StringsUtil.substringBetween(data, "{client_id:\"", "\"}},");
				return clientID;
			}
			return null;
		}
		final String data = HttpClient.getString().url(clientIDURL).create().dataThenClose();
		final String clientID = StringsUtil.substringBetween(data, "{client_id:\"", "\"}},");
		return clientID;
	}

	private static final int TRACK_DATA[] = new int[]
		{ 17, 18 };

	public static String getTrackBaseURL(final String songURL) throws Exception {
		if (!songURL.contains("soundcloud.com/")) {
			return null;
		}
		final String data0 = HttpClient.getString().url(songURL).create().dataThenClose();
		final String allObjects = StringsUtil.substringBetweenO(data0, "data.forEach(function(e){n(e)})}catch(t){}})},", "}]);") + "}]";
		final UniJsonValue uo = UniJsonValue.parseArray(allObjects);
		for (final UniJsonValue uj : uo.asArray()) {
			if (!ArrayUtils._contains(TRACK_DATA, uj.getInt("id"))) {
				continue;
			}
			final UniJsonValue data = uj.get("data").get(0);
			final UniJsonValue media = data.get("media");
			final UniJsonIterableValue transcodings = media.get("transcodings").asArray();
			final String REQUIRED_TYPE = "progressive";
			for (final UniJsonValue tc : transcodings) {
				if (!tc.get("format").getString("protocol").equalsIgnoreCase(REQUIRED_TYPE)) {
					continue;
				} else {
					return tc.getString("url");
				}
			}
		}
		throw new NullPointerException();
	}

	public static void main(final String[] args) throws Exception {
		final String URL = "https://soundcloud.com/meganeko/ultrakill";
		final String cID = getAPIKey(URL);
		log.info("API Key: " + cID);
		final String tBURL = getTrackBaseURL(URL) + "?client_id=" + cID;
		JVM.println("Track Base URL: " + tBURL);
		JVM.println("Track URL: " + UniJsonValue.parse(HttpClient.getString().url(tBURL).create().dataThenClose()).getString("url"));
	}
}
